package com.derbysoft.dswitch.adapter.ihg.dswitch2.translate;

import com.derbysoft.dswitch.adapter.ihg.common.utils.CollectionUtil;
import com.derbysoft.dswitch.adapter.ihg.common.utils.EnvironmentUtils;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.translate.Translator;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.translate.impl.TranslateHelper;
import com.derbysoft.dswitch.adapter.ihg.dto.*;
import com.derbysoft.remote.dswitch.core.GenericRQ;
import com.derbysoft.remote.dswitch.generic.constants.AgeQualifyingType;
import com.derbysoft.remote.dswitch.hotel.dto.GuestCountDTO;
import com.derbysoft.remote.dswitch.hotel.dto.HotelReservationRQ;
import com.derbysoft.remote.dswitch.hotel.dto.ReservationRoomStayDTO;
import org.apache.commons.collections.Predicate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component("ds2HotelPreviewRQTranslator")
public class HotelPreviewRQTranslator extends BaseTranslator
        implements Translator<GenericRQ<HotelReservationRQ>, OTAHotelAvailRQ, Void> {

    @Override
    public OTAHotelAvailRQ translate(GenericRQ<HotelReservationRQ> request, Void o) {
        OTAHotelAvailRQ otaHotelAvailRQ = new OTAHotelAvailRQ();
        setHeader(otaHotelAvailRQ, request.getHeader());
        otaHotelAvailRQ.setAvailRequestSegments(translateAvailRequestSegments(request));
        return otaHotelAvailRQ;
    }

    private AvailRequestSegments translateAvailRequestSegments(GenericRQ<HotelReservationRQ> request) {
        HotelReservationRQ hotelReservationRQ = request.getPayload();
        AvailRequestSegment availRequestSegment = new AvailRequestSegment();
        availRequestSegment.setAvailReqType(EnvironmentUtils.getIhgAvailabilityRequestType());
        availRequestSegment.setHotelSearchCriteria(createHotelSearchCriteria(hotelReservationRQ.getHotelReservation().getHotelRef().getCode()));
        availRequestSegment.setStayDateRange(translateStayDateRange(hotelReservationRQ.getHotelReservation().getRoomStays().get(0).getStayDateRange()));
        availRequestSegment.setRoomStayCandidates(createRoomStayCandidates(hotelReservationRQ));
        availRequestSegment.setRatePlanCandidates(createRatePlanCandidates(request.getHeader().getSource().getUniqueID().getId()));
        AvailRequestSegments availRequestSegments = new AvailRequestSegments();
        availRequestSegments.getAvailRequestSegment().add(availRequestSegment);
        return availRequestSegments;
    }

    private RoomStayCandidates createRoomStayCandidates(HotelReservationRQ hotelReservationRQ) {
        RoomStayCandidates roomStayCandidates = new RoomStayCandidates();
        roomStayCandidates.getRoomStayCandidate().add(createRoomStayCandidate(hotelReservationRQ.getHotelReservation().getRoomStays().get(0)));
        return roomStayCandidates;
    }

    private RoomStayCandidate createRoomStayCandidate(ReservationRoomStayDTO reservationRoomStayDTO) {
        RoomStayCandidate roomStayCandidate = new RoomStayCandidate();
        roomStayCandidate.setGuestCounts(translateGuestCounts(reservationRoomStayDTO.getGuestCounts()));
        roomStayCandidate.setQuantity(reservationRoomStayDTO.getNumberOfUnits());
        return roomStayCandidate;
    }

    private GuestCounts translateGuestCounts(List<GuestCountDTO> guestCountsDTO) {
        GuestCounts result = new GuestCounts();
        List<GuestCount> counts = new ArrayList<GuestCount>();
        counts.add(TranslateHelper.createAdultGuestCount(getGuestCount(guestCountsDTO, AgeQualifyingType.ADULT)));
        if (getGuestCount(guestCountsDTO, AgeQualifyingType.CHILD) != null) {
            counts.add(TranslateHelper.createChildGuestCount(getGuestCount(guestCountsDTO, AgeQualifyingType.CHILD)));
        }
        result.getGuestCount().addAll(counts);
        result.setIsPerRoom(false);
        return result;
    }

    private Integer getGuestCount(List<GuestCountDTO> guestCountsDTO, final AgeQualifyingType adult) {
        GuestCountDTO guestCountDTO = (GuestCountDTO) CollectionUtil.find(guestCountsDTO, new Predicate() {
            @Override
            public boolean evaluate(Object object) {
                return adult == ((GuestCountDTO) object).getAgeQualifyingType() && ((GuestCountDTO) object).getCount() != 0;
            }
        });
        if (guestCountDTO == null) {
            return null;
        }
        return guestCountDTO.getCount();
    }
}
